﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Serialization;
using System.IO;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Soap;
using System.Runtime.Serialization.Formatters.Binary;
using System.Xml;
using System.Web.Script.Serialization;

namespace ObjectBakery.Helpers
{
    public class SerializationHelper
    {
        public byte[] XmlSerialize(object obj)
        {
            try
            {
                using (MemoryStream stream = new MemoryStream())
                {
                    XmlSerializer xs = new
                        XmlSerializer(obj.GetType());
                    xs.Serialize(stream, obj);
                    return stream.ToArray();
                }
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to serialize. Reason: " + e.Message);
                throw;
            }
        }
        public T XmlDeserialize<T>(string serialized)
        {
            try
            {
                using (MemoryStream b =
                    new MemoryStream(Encoding.UTF8.GetBytes(serialized)))
                {
                    XmlSerializer xs = new XmlSerializer(typeof(T));
                    return (T)xs.Deserialize(b);
                }
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
                throw;
            }
        }
        public object XmlDeserialize(Type type, string serialized)
        {
            try
            {
                using (MemoryStream b =
                    new MemoryStream(Encoding.UTF8.GetBytes(serialized)))
                {
                    XmlSerializer xs = new XmlSerializer(type);
                    return xs.Deserialize(b);
                }
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
                throw;
            }
        }


        public byte[] SoapSerialize(object obj)
        {
            try
            {
                using (MemoryStream b = new MemoryStream())
                {
                    SoapFormatter formatter = new SoapFormatter();
                    formatter.Serialize(b, obj);
                    return b.ToArray();
                }
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to serialize. Reason: " + e.Message);
                throw;
            }
        }
        public T SoapDeserialize<T>(byte[] blob)
        {
            T obj = default(T);
            try
            {
                using (MemoryStream b = new MemoryStream(blob))
                {
                    SoapFormatter formatter = new SoapFormatter();
                    obj = (T)formatter.Deserialize(b);
                }
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
                throw;
            }
            return obj;
        }
        public object SoapDeserialize(byte[] blob)
        {
            object obj = default(object);
            try
            {
                using (MemoryStream b = new MemoryStream(blob))
                {
                    SoapFormatter formatter = new SoapFormatter();
                    obj = formatter.Deserialize(b);
                }
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
                throw;
            }
            return obj;
        }

        public byte[] BinarySerialize(object obj)
        {
            try
            {
                IFormatter formatter = new BinaryFormatter();
                using (MemoryStream stream = new MemoryStream())
                {
                    formatter.Serialize(stream, obj);
                    return stream.ToArray();
                }
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to serialize. Reason: " + e.Message);
                throw;
            }
        }
        public T BinaryDeserialize<T>(byte[] bytes)
        {
            try
            {
                T instance = default(T);
                IFormatter formatter = new BinaryFormatter();
                using (MemoryStream stream = new MemoryStream(bytes))
                {
                    instance = (T)formatter.Deserialize(stream);
                    bytes = stream.ToArray();
                }
                return instance;
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
                throw;
            }
        }
        public object BinaryDeserialize(byte[] bytes)
        {
            try
            {
                object instance = default(object);
                IFormatter formatter = new BinaryFormatter();
                using (MemoryStream stream = new MemoryStream(bytes))
                {
                    instance = formatter.Deserialize(stream);
                }
                return instance;
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
                throw;
            }
        }

        public  byte[] DataConractSerialize(object obj)
        {
            try
            {
                using (var stream = new MemoryStream())
                {
                    XmlWriter writer = XmlWriter.Create(stream);
                    DataContractSerializer serializer = new DataContractSerializer(obj.GetType());
                    serializer.WriteObject(writer, obj);
                    writer.Flush();
                    return stream.ToArray();
                }
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to serialize. Reason: " + e.Message);
                throw;
            }
        }
        public T DataConractDeserialize<T>(byte[] bytes)
        {
            try
            {
                T result = default(T);
                using (var stream = new MemoryStream(bytes))
                {
                    XmlReader reader = XmlReader.Create(stream);
                    DataContractSerializer serializer = new DataContractSerializer(typeof(T));
                    result = (T)serializer.ReadObject(reader);
                }
                return result;
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
                throw;
            }
        }
        public object DataConractDeserialize(Type type, byte[] bytes)
        {
            try
            {
                object result = null;
                using (var stream = new MemoryStream(bytes))
                {
                    XmlReader reader = XmlReader.Create(stream);
                    DataContractSerializer serializer = new DataContractSerializer(type);
                    result = serializer.ReadObject(reader);
                }
                return result;
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
                throw;
            }
        }
        
        public  string JsonSerialize(object obj)
        {
            try
            {
                return new JavaScriptSerializer().Serialize(obj);
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to serialize. Reason: " + e.Message);
                throw;
            }
        }
        public  T JsonDeserialize<T>(string json)
        {
            try
            {
                return new JavaScriptSerializer().Deserialize<T>(json);
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
                throw;
            }
        }
        public object JsonDeserialize(string json)
        {
            try
            {
                return new JavaScriptSerializer().DeserializeObject(json);
            }
            catch (SerializationException e)
            {
                Console.WriteLine("Failed to deserialize. Reason: " + e.Message);
                throw;
            }
        }
    }
}
